package com.zlp.mall.modules.pms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlp.mall.common.api.Pager;
import com.zlp.mall.common.api.RespCode;
import com.zlp.mall.common.exception.CustomException;
import com.zlp.mall.common.util.BeanToUtils;
import com.zlp.mall.common.util.MethodUtil;
import com.zlp.mall.modules.pms.dto.req.ProductCategoryAddReq;
import com.zlp.mall.modules.pms.dto.req.ProductCategoryUpdReq;
import com.zlp.mall.modules.pms.dto.resp.ProductCateChildrenResp;
import com.zlp.mall.modules.pms.dto.resp.ProductCategoryResp;
import com.zlp.mall.modules.pms.mapper.ProductCategoryMapper;
import com.zlp.mall.modules.pms.model.Product;
import com.zlp.mall.modules.pms.model.ProductCategory;
import com.zlp.mall.modules.pms.model.ProductCategoryAttributeRelation;
import com.zlp.mall.modules.pms.service.ProductCategoryAttributeRelationService;
import com.zlp.mall.modules.pms.service.ProductCategoryService;
import com.zlp.mall.modules.pms.service.ProductService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品分类 服务实现类
 * </p>
 *
 * @author ZouLiPing
 * @since 2021-09-23
 */
@Service
@RequiredArgsConstructor
@Slf4j(topic = "ProductCategoryServiceImpl")
public class ProductCategoryServiceImpl extends ServiceImpl<ProductCategoryMapper, ProductCategory> implements ProductCategoryService {
    @Resource
    private ProductService productService;
    private final ProductCategoryAttributeRelationService productCategoryAttributeRelationService;


    @Override
    public Pager<ProductCategoryResp> list(Long parentId, String keyword, Integer pageSize, Integer pageNum) {

        log.info("list.req parentId={},keyword={},pageSize={},pageNum={}", parentId, keyword, pageSize, pageNum);
        Page pages = new Page(pageNum, pageSize);
        // 条件构造器
        LambdaQueryWrapper<ProductCategory> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(ProductCategory::getSort);
        if (Objects.nonNull(parentId)) {
            wrapper.eq(ProductCategory::getParentId, parentId);
        } else {
            // 默认查询一级商品分类
            wrapper.eq(ProductCategory::getParentId, 0);
        }
        if (StrUtil.isNotBlank(keyword)) {
            wrapper.like(ProductCategory::getName, keyword);
        }
        Page page = this.page(pages, wrapper);
        List records = page.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            List<ProductCategoryResp> resps = BeanToUtils.entityToList(records, ProductCategoryResp.class);
            return new Pager(resps, page.getTotal(), pageSize, pageNum);
        }
        return new Pager<>();
    }

    @Override
    public List<ProductCateChildrenResp> getWithChildren() {

        log.info("getWithChildren");
        LambdaQueryWrapper<ProductCategory> queryWrapper = new LambdaQueryWrapper<>();
        List<ProductCategory> list = this.list(queryWrapper);
        List<ProductCateChildrenResp> productCategoryResps = BeanToUtils.entityToList(list, ProductCateChildrenResp.class);

        List<ProductCateChildrenResp> oneLevelResps = productCategoryResps.stream().filter(
                childrenResp -> Objects.equals(childrenResp.getParentId(), 0L)).collect(Collectors.toList());

        oneLevelResps = getSortedTree(oneLevelResps);

        for (ProductCateChildrenResp oneLevelResp : oneLevelResps) {
            oneLevelResp.setChildren(getChildTree(oneLevelResp, productCategoryResps));
        }
        return oneLevelResps;

    }

    private List<ProductCateChildrenResp> getChildTree(ProductCateChildrenResp oneLevelResp, List<ProductCateChildrenResp> productCategoryResps) {

        List<ProductCateChildrenResp> treeRespList;

        treeRespList = productCategoryResps.stream().filter(productCategory -> Objects.equals(productCategory.getParentId(), oneLevelResp.getId())).
                collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(treeRespList)) {
            for (ProductCateChildrenResp treeResp : treeRespList) {
                treeResp.setChildren(getChildTree(treeResp, productCategoryResps));
            }
        }
        // 降序排序
        treeRespList = getSortedTree(treeRespList);
        return treeRespList;
    }

    /**
     * 降序排序
     *
     * @param treeRespList
     * @date: 2021/9/29 16:34
     * @return: java.util.List<com.zlp.mall.modules.pms.dto.resp.ProductCateChildrenResp>
     */
    private List<ProductCateChildrenResp> getSortedTree(List<ProductCateChildrenResp> treeRespList) {

        return treeRespList.stream().sorted(Comparator.comparing(ProductCateChildrenResp::getSort)).collect(Collectors.toList());
    }


    @Override
    public boolean updateNavStatus(List<Long> ids, Integer navStatus) {

        log.info("updateNavStatus.req ids={},navStatus={}", ids, navStatus);
        LambdaUpdateWrapper<ProductCategory> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                // 需要更新的列
                .set(ProductCategory::getNavStatus, navStatus)
                // 条件
                .in(ProductCategory::getId, ids);
        return this.update(updateWrapper);
    }

    @Override
    public boolean delete(Long id) {

        log.info("delete.req id={}", id);
        this.getInfoById(id);
        List<ProductCategory> childrens = this.getChildProductCategory(id);
        // 校验商品分类是否绑定商品
        List<Long> catIds = childrens.stream().map(ProductCategory::getId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(catIds)) {
            List<Product> productList = productService.getProductByCategoryIds(catIds);
            if (CollectionUtil.isNotEmpty(productList)) {
                throw new CustomException(RespCode.BACK_PMS_3003, MethodUtil.getLineInfo());
            }
        }
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(ProductCategoryUpdReq productCategoryUpdReq) {

        log.info("update.req productCategoryUpdReq={}", JSON.toJSONString(productCategoryUpdReq));

        ProductCategory productCategory = BeanToUtils.dtoToDo(productCategoryUpdReq, ProductCategory.class);
        if (Objects.equals(productCategory.getParentId(), 0L)) {
            productCategory.setLevel(0);
        } else {
            // 如果有多级分类，根据parentId查出商品分类获取level+1
            // 由于只有2级分类，直接设置为1
            productCategory.setLevel(1);
        }
        this.updateById(productCategory);
        // 删除已保存的关联属性—根据商品分类id删除
        QueryWrapper<ProductCategoryAttributeRelation> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ProductCategoryAttributeRelation::getProductCategoryId, productCategory.getId());
        productCategoryAttributeRelationService.remove(queryWrapper);
        saveAttrRelation(productCategoryUpdReq.getProductAttributeIdList(), productCategory);
        return Boolean.TRUE;
    }

    @Override
    public ProductCategoryResp getInfoById(Long id) {

        log.info("getInfoById.req id={}", id);
        ProductCategory productCategory = this.getById(id);
        return BeanToUtils.doToDto(productCategory, ProductCategoryResp.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(ProductCategoryAddReq productCategoryAddReq) {

        log.info("create.req productCategoryAddReq={}", JSON.toJSONString(productCategoryAddReq));
        ProductCategory productCategory = BeanToUtils.dtoToDo(productCategoryAddReq, ProductCategory.class);
        // 由于商品数量 和级别 在表单中没有维护， 需要设置默认值
        productCategory.setProductCount(0);
        if (Objects.equals(productCategory.getParentId(), 0L)) {
            productCategory.setLevel(0);
        } else {
            // 如果有多级分类，根据parentId 查出商品分类获取 level+1
            // 由于只有2级分类，直接设置为1
            productCategory.setLevel(1);
        }
        this.save(productCategory);
        saveAttrRelation(productCategoryAddReq.getProductAttributeIdList(), productCategory);
        return true;
    }

    @Override
    public boolean updateShowStatus(List<Long> ids, Integer showStatus) {
        log.info("updateShowStatus.req ids={},showStatus={}", ids, showStatus);
        LambdaUpdateWrapper<ProductCategory> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                // 需要更新的列
                .set(ProductCategory::getShowStatus, showStatus)
                // 条件
                .in(ProductCategory::getId, ids);
        return this.update(updateWrapper);
    }

    @Override
    public List<ProductCategory> getChildProductCategory(Long parentId) {

        log.info("getChildProductCategory.req parentId={}", parentId);
        List<ProductCategory> categoryList = new ArrayList<>();
        LambdaQueryWrapper<ProductCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductCategory::getParentId, parentId);
        List<ProductCategory> childList = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(childList)) {
            categoryList.addAll(childList);
            for (ProductCategory productCategory : childList) {
                categoryList.addAll(getChildProductCategory(productCategory.getId()));
            }
        }
        return childList;
    }


    /**
     * 添加商品属性关联关系
     *
     * @param productAttributeIdList
     * @param productCategory
     * @date: 2021/9/27 13:47
     * @return: void
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveAttrRelation(List<Long> productAttributeIdList, ProductCategory productCategory) {

        List<ProductCategoryAttributeRelation> list = new ArrayList<>();
        for (Long attrId : productAttributeIdList) {
            // 得到分类保存后的主键id,   保存商品分类筛选属性关系
            ProductCategoryAttributeRelation productCategoryAttributeRelation = new ProductCategoryAttributeRelation();
            productCategoryAttributeRelation.setProductCategoryId(productCategory.getId());
            productCategoryAttributeRelation.setProductAttributeId(attrId);
            list.add(productCategoryAttributeRelation);
        }
        return productCategoryAttributeRelationService.saveBatch(list);
    }
}
